﻿using BattleServer;
using Newtonsoft.Json.Linq;
using PECommon;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BattleServer.Battle
{
    /// <summary>
    /// 战斗世界容器
    /// </summary>
    public class WorldContainer : ILogic
    {
        private int ContainerID;
        private BattleWorldSys mWorldSys;
        private List<SWorld> mWorldList = new List<SWorld>();
        private ConcurrentQueue<ulong> mCreatingWorlds = new ConcurrentQueue<ulong>();
        private CancellationToken mToken;
        private CancellationTokenSource mTokenSouce;

        private DateTime mLastFPSTime = DateTime.Now;
        private int mFrameCounter = 0;
        public int mFPS;
        public DateTime mLastTickTime = DateTime.Now;
        public float mDeltaTime;
        public float DeltaTime { get => mDeltaTime; set => mDeltaTime = value; }

        public WorldContainer(int containerID, BattleWorldSys worldSys)
        {
            mTokenSouce = new CancellationTokenSource();
            mToken = mTokenSouce.Token;
            ContainerID = containerID;
            mWorldSys = worldSys;
        }

        public void Awake()
        {
            Task.Run(Update);
        }


        public async void Update()
        {
            try
            {
                while (true)
                {
                    await Task.Delay(1);
                    Thread.Sleep(1);

                    while (mCreatingWorlds.TryDequeue(out ulong worldID))
                    {
                        SWorld world = CreateGameWorld(worldID);
                        if (world != null)
                        {
                            world.Container = this;
                            world.Awake();
                            mWorldSys.AddGameWorld(world);
                            mWorldList.Add(world);
                        }
                    }

                    if (!mToken.IsCancellationRequested)
                    {
                        DateTime now = DateTime.Now;
                        ++mFrameCounter;
                        if ((now - mLastFPSTime).TotalMilliseconds > 1000)
                        {
                            mFPS = mFrameCounter;
                            mFrameCounter = 0;
                            mLastFPSTime = now;
                        }
                        DeltaTime = (float)(now - mLastTickTime).TotalSeconds;
                        mLastTickTime = now;
                        for (int i = mWorldList.Count - 1; i >= 0; i--)
                        {
                            if (mWorldList[i].IsDestroy)
                            {
                                mWorldSys.RemoveGameWorld(mWorldList[i].WorldID);
                                mWorldList[i].Destory();

                                mWorldList.RemoveAt(i);
                            }
                            else
                            {
                                mWorldList[i].Update();
                            }
                        }
                    }
                    else
                    {
                        for (int i = mWorldList.Count - 1; i >= 0; i--)
                        {
                            mWorldList[i].Destory();
                            mWorldSys.RemoveGameWorld(mWorldList[i].WorldID);
                        }
                        mWorldList.Clear();
                        break;
                    }



                }
            }
            catch (Exception e)
            {
                this.Error($"GameWorld Container:{ContainerID} Error:{e}");
                throw;
            }
        }

        public void Destory()
        {
            mTokenSouce.Cancel();
            while (true)
            {
                if (mWorldList.Count != 0)
                {
                    Thread.Sleep(5);
                }
                else break;
            }
            mTokenSouce = null;
        }
        private SWorld CreateGameWorld(ulong world)
        {
            return null;
        }

        public void AddGameWorldID(ulong worldID)
        {
            mCreatingWorlds.Enqueue(worldID);
        }
    }
}
